package info.niwota.ziplock;

import java.util.ArrayList;
import java.util.List;

import android.app.Dialog;
import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;

/**
 * 
 * @author qiangli
 * 
 */
public class ZipFileListActivity extends ListActivity implements
		OnClickListener {
	public static final String EXTRA_URIS = "extra.uris"; //

	private Handler progressHandler = new Handler() {

		public void handleMessage(Message msg) {
			CharSequence m = statusMonitor.message;
			if (Debug.DEBUG) {
				Log.d(TAG, "message: " + m);
			}
			progressDialog.setTitle(m);
		}
	};

	private class InitTask extends AsyncTask<Void, Void, Void> {

		private Exception error;

		@Override
		protected void onCancelled() {
			dismissDialog(DIALOG_PROGRESS);
		}

		@Override
		protected void onPreExecute() {
			showDialog(DIALOG_PROGRESS);
		}

		@Override
		protected Void doInBackground(Void... params) {
			try {
				load();
			} catch (Exception e) {
				error = e;
			}
			return null;
		}

		@Override
		protected void onPostExecute(Void result) {
			if (error != null) {
				showMessage("" + error.getMessage());
			}
			try {
				updateUi();
			} finally {
				dismissDialog(DIALOG_PROGRESS);
			}
		}
	}

	private static final String TAG = "ZipFileListActivity";

	private static final int DIALOG_PROGRESS = 2;

	private static final int RC_VIEW = 1;

	private ArrayAdapter<FileItem> adapter;

	private ArrayList<FileItem> files = new ArrayList<FileItem>();

	// private ArrayAdapter<NameIndex> viewSelectedItems;

	private Button btnOk;

	private Button btnCancel;

	private ProgressDialog progressDialog;

	private StatusMonitor statusMonitor = new StatusMonitor();

	private ArrayList<FileItem> list;

	private String zipname;

	private boolean pick;;

	private int getCount() {
		return adapter.getCount();
	}

	private int getSelectedCount() {
		SparseBooleanArray ps = getListView().getCheckedItemPositions();
		int size = adapter.getCount();
		int cnt = 0;
		for (int i = 0; i < size; i++) {
			if (ps.get(i)) {
				cnt++;
			}
		}
		return cnt;
	}

	private ArrayList<FileItem> getSelectedItems() {
		SparseBooleanArray ps = getListView().getCheckedItemPositions();
		ArrayList<FileItem> ck = new ArrayList<FileItem>();
		int size = adapter.getCount();
		for (int i = 0; i < size; i++) {
			if (ps.get(i)) {
				ck.add(adapter.getItem(i));
			}
		}
		return ck;
	}

	private void updateUi() {
		// set to reload
		getListView().setAdapter(adapter);
		//
		ListView v = getListView();
		v.clearChoices();
		if (list != null) {
			FileItem[] el = list.toArray(new FileItem[0]);
			int pos = 0;
			for (FileItem a : files) {
				boolean ck = false;
				if (el != null) {
					for (int i = 0; i < el.length; i++) {
						if (el[i].equals(a)) {
							ck = true;
							break;
						}
					}
				}
				v.setItemChecked(pos++, ck);
			}
		}

		refreshUi(v);
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		if (Debug.DEBUG) {
			Log.d(TAG, "onCreate: " + savedInstanceState);
		}
		//
		requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
		// requestWindowFeature(Window.FEATURE_LEFT_ICON);
		setContentView(R.layout.zip_file_list);
		//
		pick = isPickAction();
		adapter = new ArrayAdapter<FileItem>(this,
				(pick ? R.layout.zip_file_item : R.layout.zip_file_item2),
				files);

		setProgressBarIndeterminate(true);
		//
		final ListView lv = getListView();
		lv.setAdapter(adapter);
		lv.setItemsCanFocus(false);
		lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
		//
		// getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON,
		// R.drawable.icon25);
		//
		View buttons = findViewById(R.id.buttons);
		buttons.setVisibility(pick ? View.VISIBLE : View.GONE);
		btnOk = (Button) findViewById(R.id.button_ok);
		btnCancel = (Button) findViewById(R.id.button_cancel);
		btnOk.setOnClickListener(this);
		btnCancel.setOnClickListener(this);
		//
		init();

		if (savedInstanceState != null) {
			restoreState();
			//
			updateUi();
		} else {
			initLoad();
		}
		//
		if (Debug.DEBUG) {
			Log.d(TAG, " onCraete");
		}
	}

	private boolean isPickAction() {
		String action = getIntent().getAction();
		return (action != null && (action.equals(Intent.ACTION_PICK) || action
				.equals(Intent.ACTION_GET_CONTENT)));
	}

	private void showItem(FileItem item) {
		try {
			Uri zip = getIntent().getData();
			Uri uri = FileContentProvider.constructUri(zip, item.getName());
			AppUtils.showItem(this, uri, RC_VIEW);
		} catch (Exception e) {
			showError(e);
		}
	}

	private void showError(Exception e) {
		Toast.makeText(this, "" + e.getMessage(), Toast.LENGTH_SHORT).show();
	}

	@SuppressWarnings("unchecked")
	private void restoreState() {
		Object[] obj = (Object[]) getLastNonConfigurationInstance();
		if (obj == null) {
			initLoad();
			return;
		}
		String title = (String) obj[0];
		setTitle(title);
		ArrayList<FileItem> il = (ArrayList<FileItem>) obj[1];
		list = il;
		ArrayList<FileItem> al = (ArrayList<FileItem>) obj[2];
		if (al != null) {
			files.addAll(al);
		}
	}

	private void init() {
		try {
			files.clear();
			list = null;
			//
			zipname = getIntent().getData().getLastPathSegment();
			setTitle(zipname);
			//
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	protected Dialog onCreateDialog(int id) {
		switch (id) {
		case DIALOG_PROGRESS:
			progressDialog = createProgressDialog();
			return progressDialog;
		default:
		}
		return null;
	}

	private ProgressDialog createProgressDialog() {
		final Context ctx = this;
		ProgressDialog pd = new ProgressDialog(ctx);
		Uri uri = getIntent().getData();
		pd.setTitle(uri.getPath());
		pd.setMessage(ctx.getText(R.string.wait));
		pd.setIndeterminate(true);
		pd.setCancelable(true);
		DialogInterface.OnClickListener l = new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				statusMonitor.aborted = true;
			}
		};
		pd.setButton(ProgressDialog.BUTTON_POSITIVE,
				getString(R.string.button_cancel), l);
		return pd;
	}

	private void initLoad() {
		InitTask task = new InitTask();
		task.execute();
	}

	private void load() throws Exception {
		Uri uri = getIntent().getData();
		statusMonitor.aborted = false;
		statusMonitor.handler = progressHandler;
		//
		FileContentProvider.load(uri, statusMonitor, files);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater mif = getMenuInflater();
		mif.inflate(R.menu.views_options, menu);
		MenuItem miList = menu.findItem(R.id.views_list_opt_menu_id);
		MenuItem miThumbnails = menu.findItem(R.id.views_thumbnails_opt_menu_id);
		miList.setEnabled(false);
		miThumbnails.setEnabled(true);
		
		return true;
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			if (pick && getSelectedCount() > 0) {
				return true;
			}
			doCancel();
			return true;
		}
		return super.onKeyDown(keyCode, event);
	}

	private void doCancel() {
		setResult(RESULT_CANCELED);
		finish();
	}

	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		if (isPickAction()) {
			int sc = getSelectedCount();
			updateTitle(sc);
			showOrHideActions(sc > 0);
		} else {
			FileItem fi = files.get(position);
			showItem(fi);
		}

	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (Debug.DEBUG) {
			Log.d(TAG, "requestCode: " + requestCode + " resultCode: "
					+ resultCode + " data: " + data);
		}
		if (requestCode == RC_VIEW) {
			//
			return;
		}
	}

	public void onClick(View v) {
		int id = v.getId();
		switch (id) {
		case R.id.button_ok:
			doFinish();
			break;
		case R.id.button_cancel:
			doCancel();
			break;
		}
	}

	private void doFinish() {
		ArrayList<Uri> list = new ArrayList<Uri>();
		List<FileItem> sel = getSelectedItems();
		//
		Uri uri = getIntent().getData();
		if (Debug.DEBUG) {
			Log.d(TAG, "uri: " + uri);
		}

		String zipname = uri.getLastPathSegment();
		Uri base = FileContentProvider.constructBaseUri(zipname);
		
		for (FileItem i : sel) {
			String p = i.getName();
			Uri u = Uri.withAppendedPath(base, p);
			if (Debug.DEBUG) {
				Log.d(TAG, "selected uri: " + u);
			}
			list.add(u);
		}

		Intent data = new Intent();
		data.putParcelableArrayListExtra(EXTRA_URIS, list);

		setResult(RESULT_OK, data);
		finish();
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch(item.getItemId()) {
		case R.id.views_list_opt_menu_id:
			return false;
		case R.id.views_thumbnails_opt_menu_id:
			doSwitchView();
			return true;
		}
		return false;
	}

	private void doSwitchView() {
		Intent data = getIntent();
		data.putExtra(ViewsActivity.EXTRA_VIEW, Preferences.VIEW_THUMBNAILS);
		setResult(RESULT_FIRST_USER, data);
		finish();
	}

	@Override
	protected void onPrepareDialog(int id, Dialog dialog) {
		switch (id) {
		case DIALOG_PROGRESS:
			// progressDialog.setTitle();
			break;
		}
	}

	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		return true;
	}

	@Override
	public Object onRetainNonConfigurationInstance() {
		Object[] obj = new Object[3];
		obj[0] = getTitle();
		obj[1] = getSelectedItems();
		obj[2] = files;
		return obj;
	}

	private void refreshUi(ListView v) {
		if (pick) {
			int sc = getSelectedCount();
			updateTitle(sc);
			showOrHideActions(sc > 0);
		}
		v.requestLayout();
	}

	private void showOrHideActions(boolean b) {
		btnOk.setEnabled(b);
	}

	void showMessage(String msg) {
		Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
	}

	private void updateTitle(int sc) {
		int tc = getCount();

		String t = (tc > 0 ? getString(R.string.title_list_found, zipname, sc,
				tc) : getString(R.string.title_list_not_found, zipname));
		setTitle(t);
	}
}
